home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Mac Game Programming Gurus / TricksOfTheMacGameProgrammingGurus.iso / More Source / C⁄C++ / AIFF DSP v22 / plugin_src / sintab.c < prev    next >
Text File  |  1995-01-30  |  3KB  |  97 lines

  1. /* sine table generation & lookup code */
  2.  
  3. #include "aiff.h"
  4. #include "sintab.h"
  5. #include "num_input_macros.h"
  6.  
  7. #include <stdio.h>
  8. #include <stdlib.h>
  9. #include <math.h>
  10.  
  11. #define HALFPI  1.5707963 /* half of pi */
  12. #define SINAMP  0x7FFF    /* sine wave amplitude */
  13.  
  14. short sintab[QSIZ+1];
  15.  
  16. double round( double x )
  17. {
  18.    double offset = 0.5;
  19.    if ( x < 0.0 ) offset = -offset;
  20.    return  x + offset;
  21. }
  22.  
  23. /* puts a 1st-quadrant sine table into sintab[] */
  24. void get_sintab ( void )
  25. {
  26.    short i;
  27.    
  28.    sintab[0]    = 0;
  29.    sintab[QSIZ] = SINAMP;
  30.    for (i=1; i < QSIZ; i++)
  31.       sintab[i] = round( SINAMP * sin( HALFPI * i / QSIZ ) );
  32. }
  33. /*
  34. 1. Small enough means that the correct last value is found where expected.
  35. 2. Does not deserve a call to exit because a file error here does not impede
  36.    function of program and therefore is not a fatal error.
  37. */
  38.  
  39. /* puts a full 4-quadrant sine table into sintab4[] using sintab() */
  40. short *gen_sintab4 ( void )
  41. {
  42.    unsigned short i;
  43.    short *sintab4, *tsintab4;
  44.  
  45.    if (!(sintab4 = malloc( 2L*4*QSIZ )))
  46.       err( "Could not allocate 4-quadrant sine table memory" );
  47.  
  48.    tsintab4 = sintab4;
  49.    for (i=0; i<4*QSIZ; i++)
  50.       *tsintab4++ = sin_tab( i );
  51.    return sintab4;
  52. }
  53.  
  54. /* returns SINAMP * sin (pi/2 * tabi/QSIZ) using sintab[] */
  55. /* tabi is assumed to be non-negative */
  56. short sin_tab( short tabi )
  57. {
  58.    register short i;
  59.  
  60.    i = tabi & (2*QSIZ-1); /* i = tabi % 2QSIZ; */
  61.    if ( i & QSIZ )        /* if ( i >= QSIZ ) */
  62.       i = 2*QSIZ - i;    /* reflect i from the 2nd to the 1st quadrant */
  63.    if ( tabi & (2*QSIZ) ) /* if ( (tabi % 4QSIZ) >= 2QSIZ ) */
  64.       return -sintab[i]; /* negate sintab[i] if in 3rd or 4th quadrant */
  65.    else return sintab[i];
  66. }
  67.  
  68. /* getusrharm() asks the user for a frequency and returns number of the */
  69. /* closest harmonic of the sine table frequency */
  70. short getusrharm( double rate )
  71. {
  72.    double infreq, oufreq, tabfreq, centerr;
  73.    short retval;
  74.  
  75.    GET_NUM_RANGE( "frequency", "%.1f", "%lf", infreq, 0.0, rate/2 );
  76.  
  77.    if ( infreq == 0.0 ) return 0;
  78.    tabfreq = rate / (4*QSIZ);    /* sine table frequency (1) */
  79.    retval = infreq / tabfreq + 0.5; /* (2) */
  80.    if (!retval) retval++;           /* bump 0th harmonic up to 1st */
  81.    oufreq = tabfreq * retval;       /* output frequency */
  82.    if (oufreq > rate/2) {           /* if Nyquist freq. exceeded */
  83.       oufreq -= tabfreq;            /* bump oufreq down 1 harmonic */
  84.       retval--;                     /* bump retval down 1 harmonic */
  85.    }
  86.    centerr = 1200 * log( oufreq/infreq ) / log(2);            /* 3 */
  87.    fprintf( stderr, "\tUsing %.3f Hz, %.3f Hz or %.1f cents away\n\n",
  88.             oufreq, oufreq - infreq, centerr );
  89.    return retval;
  90. }
  91. /*
  92. 1. sine table frequency >= 1 Hz ==> 4*QSIZ <= 44100 < 0x10000 ==> 4*QSIZ
  93.    fits in an unsigned word.
  94. 2. harmonic of tabfreq closest to infreq (+ 0.5 rounds).
  95. 3. cent error is the interval between oufreq and infreq
  96. */
  97.